use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{RwLock, RwLockWriteGuard, RwLockReadGuard};

pub struct HttpState<T> {
    inner: Arc<RwLock<T>>,
}

pub struct HttpStateContainer {
    map: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
}

impl<T> HttpState<T> {
    pub fn new(data: T) -> Self {
        HttpState {
            inner: Arc::new(RwLock::new(data)),
        }
    }
}

impl<T> Clone for HttpState<T> {
    fn clone(&self) -> Self {
        Self {
            inner: self.inner.clone(),
        }
    }
}

impl<T> HttpState<T>
where
    T: Send + Sync + 'static,
{
    pub async fn read(&self) -> RwLockReadGuard<'_, T> {
        self.inner.read().await
    }

    pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
        self.inner.write().await
    }
}

impl HttpStateContainer {
    pub fn new() -> Self {
        Self {
            map: HashMap::new(),
        }
    }

    pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) {
        self.map.insert(TypeId::of::<T>(), Arc::new(RwLock::new(value)));
    }

    pub fn get<T: Send + Sync + 'static>(&self) -> Option<HttpState<T>> {
        self.map
            .get(&TypeId::of::<T>())
            .and_then(|v| v.clone().downcast_arc::<RwLock<T>>().ok())
            .map(|inner| HttpState { inner })
    }
}

trait DowncastArc {
    fn downcast_arc<T: Any + Send + Sync>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>;
}

impl DowncastArc for dyn Any + Send + Sync {
    fn downcast_arc<T: Any + Send + Sync>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
        if self.is::<T>() {
            let ptr = Arc::into_raw(self) as *const T;
            Ok(unsafe { Arc::from_raw(ptr) })
        } else {
            Err(self)
        }
    }
}


#[allow(unused)]
#[cfg(test)]
mod tests {
    use super::*;

    #[derive(Debug)]
    struct AppState {
        counter: usize,
    }   

    #[tokio::test]
    async fn test() {
        let mut state = HttpStateContainer::new();

        state.insert(AppState { counter: 0 });
    
        if let Some(shared_state) = state.get::<AppState>() {
            {
                // 并发读
                let read_guard = shared_state.read().await;
                println!("Current counter: {}", read_guard.counter);
            }
    
            {
                // 独占写
                let mut write_guard = shared_state.write().await;
                write_guard.counter += 1;
                println!("Counter incremented: {}", write_guard.counter);
            }
    
            {
                // 并发读
                let read_guard = shared_state.read().await;
                println!("Current counter: {}", read_guard.counter);
            }
        }
    }
}